/**
 * Rubik is a for-testing-purposes simple CMS.
 * Copyright (C) 2010 Antonio Hernandez Diaz <ahdiaz@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * $Id: SednaDocCollection.java 8 2010-04-13 19:10:09Z ahdiaz $
 */

package net.ahdiaz.rubik.model;

import java.util.Collection;
import java.util.HashMap;

import javax.xml.bind.JAXBException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import net.ahdiaz.rubik.sedna.SednaMarshaller;
import ru.ispras.sedna.driver.DriverException;

public abstract class SednaDocCollection extends SednaCollection {

	protected String docName;
	protected String rootNode;
	protected String colNode;

	public SednaDocCollection(String colName, String docName, String rootNode, String colNode) throws DriverException {
		super(colName);
		this.docName = docName;
		this.rootNode = rootNode;
		this.colNode = colNode;
	}

	@Override
	protected String getDocNameFromObject(Object item) {
		// Not used
		return null;
	}
	
	protected abstract String getPathFromObject(Object item);
	
	public boolean append(Object item) throws DriverException, JAXBException {
				
		try {
			
			String s = SednaMarshaller.marshal(item, false, true).toString();
						
			String query = null;
			if (colName != null) {
				query = "UPDATE insert %doc into doc('%docName', '%colName')%rootNode";
			} else {
				query = "UPDATE insert %doc into doc('%docName')%rootNode";
			}
			
			query = query
				.replaceAll("%docName", docName)
				.replaceAll("%rootNode", rootNode)
				.replaceAll("%colName", colName)
				.replaceAll("%doc", s);
			
			this.query(query);
			
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return true;
	}
	
	public boolean update(Object item) throws DriverException, JAXBException {
				
		try {
			
			String s = SednaMarshaller.marshal(item, false, true).toString();
						
			String query = null;
			if (colName != null) {
				query = "UPDATE replace $node in doc('%docName', '%colName')%rootNode%nodePath with %doc";
			} else {
				query = "UPDATE replace $node in doc('%docName')%rootNode%nodePath with $doc";
			}
			
			query = query
				.replaceAll("%docName", docName)
				.replaceAll("%rootNode", rootNode)
				.replaceAll("%nodePath", this.getPathFromObject(item))
				.replaceAll("%colName", colName)
				.replaceAll("%doc", s);
			
			this.query(query);
			
		} catch (TransformerFactoryConfigurationError e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return true;
	}
	
	public boolean remove(Object item) throws DriverException, JAXBException {
				
		String query = null;
		if (colName != null) {
			query = "UPDATE delete doc('%docName', '%colName')%rootNode%nodePath";
		} else {
			query = "UPDATE delete doc('%docName')%rootNode%nodePath";
		}
		
		query = query
			.replaceAll("%docName", docName)
			.replaceAll("%rootNode", rootNode)
			.replaceAll("%nodePath", this.getPathFromObject(item))
			.replaceAll("%colName", colName);
		
		this.query(query);
		return true;
	}
	
	public Object readByName(String nodeName) throws JAXBException, DriverException {

		String query;
		if (colName == null) {
			query = "doc('%docName')%rootNode%colNode[@name='%nodeName']";
		} else {
			query = "doc('%docName', '%colName')%rootNode%colNode[@name='%nodeName']";
		}
		
		query = query
			.replaceAll("%colName", colName)
			.replaceAll("%docName", docName)
			.replaceAll("%rootNode", rootNode)
			.replaceAll("%colNode", colNode)
			.replaceAll("%nodeName", nodeName);
		
		Object result = null;
		Collection<?> c = this.query(query);
		
		if (c.size() == 1) {
			result = c.iterator().next();
		}
		
		return result;
	}

	public Object readByUID(String uid) throws JAXBException, DriverException {

		String query;
		if (colName == null) {
			query = "doc('%docName')%rootNode%colNode[@uid='%nodeUID']";
		} else {
			query = "doc('%docName', '%colName')%rootNode%colNode[@uid='%nodeUID']";
		}
		
		query = query
			.replaceAll("%colName", colName)
			.replaceAll("%docName", docName)
			.replaceAll("%rootNode", rootNode)
			.replaceAll("%colNode", colNode)
			.replaceAll("%nodeUID", uid);
		
		Object result = null;
		Collection<?> c = this.query(query);
		
		if (c.size() == 1) {
			result = c.iterator().next();
		}
		
		return result;
	}

	public Collection<?> readAll() throws JAXBException, DriverException {
		return this.readAll(null);
	}
	
	public Collection<?> readAll(HashMap<String, String> constraints) throws JAXBException, DriverException {
		//query = "doc('%docName', '%colName')//collection[@name='%colName']/document[contains(@name, '%docName')]/@name";

		String query;
		if (colName == null) {
			query = "doc('%docName')%rootNode%colNode";
		} else {
			query = "doc('%docName', '%colName')%rootNode%colNode";
		}
		query = query
			.replaceAll("%colName", colName)
			.replaceAll("%docName", docName)
			.replaceAll("%rootNode", rootNode)
			.replaceAll("%colNode", colNode);
		
		Collection<?> c = this.query(query);		
		return c;
	}

}
